package com.seleniti.enpareja.web.desktop.client.ui.widget;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.ioc.commons.extra.gwt.extensions.renderer.client.HasLabelRenderer;
import org.ioc.commons.impl.gwt.client.ui.DisplayComposite;
import org.ioc.commons.impl.gwt.client.ui.HasEnabledWrapper;
import org.ioc.commons.impl.gwt.client.ui.HasLoaderWrapper;
import org.ioc.commons.impl.gwt.client.ui.HasTextWrapper;
import org.ioc.commons.impl.gwt.client.ui.HasValueWrapper;
import org.ioc.commons.impl.gwt.client.ui.HasVisibilityWrapper;
import org.ioc.commons.ui.HasEnabled;
import org.ioc.commons.ui.HasLoader;
import org.ioc.commons.ui.HasText;
import org.ioc.commons.ui.HasValue;
import org.ioc.commons.ui.HasVisibility;
import org.ioc.commons.ui.features.Info;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.FieldSetElement;
import com.google.gwt.dom.client.HeadingElement;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Html5FormPanel;
import com.google.gwt.user.client.ui.Html5MailBox;
import com.google.gwt.user.client.ui.Html5PasswordBox;
import com.google.gwt.user.client.ui.Html5TextBox;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.SubmitButton;
import com.google.gwt.user.client.ui.ValueListBox;
import com.google.gwt.user.client.ui.Widget;
import com.seleniti.enpareja.controller.model.integration.database.domain.Gender;
import com.seleniti.enpareja.controller.model.integration.database.domain.User;
import com.seleniti.enpareja.controller.ui.widget.UserForm;
import com.seleniti.enpareja.controller.ui.widget.UserForm.Action;
import com.seleniti.enpareja.controller.ui.widget.UserForm.Event;
import com.seleniti.enpareja.controller.ui.widget.UserForm.Operation;
import com.seleniti.enpareja.controller.ui.widget.UserForm.Presenter;
import com.seleniti.enpareja.controller.ui.widget.UserFormPresenter;

public class UserFormWidget extends DisplayComposite<Event, Operation, Action, Presenter> implements UserForm {

	@UiField(provided = true)
	ValueListBox<Gender> gender;

	@UiField
	InfoInlineWidget userEmailCheckInfo;

	@UiField
	InfoInlineWidget passwordCheckInfo;

	@UiField
	Html5MailBox userEmail;

	@UiField
	Html5TextBox nickName;

	@UiField
	Html5PasswordBox password;

	@UiField
	Html5PasswordBox password2;

	@UiField
	HeadingElement caption;

	@UiField
	SubmitButton btnSave;

	@UiField
	FieldSetElement fieldSet;

	@UiField
	Html5FormPanel form;

	@UiField
	InfoInlineWidget extraInfo;

	private boolean enabled = true;

	@UiField
	DivElement gettingLoader;

	@UiField
	DivElement savingLoader;

	@UiField
	DivElement breakingUpLoader;

	@UiField
	DivElement dropSingleModeLoader;

	@UiField
	DivElement dropTestModeLoader;

	@UiField
	Panel couplePanel;

	@UiField
	Panel singlePanel;

	@UiField
	Panel testPanel;

	@UiField
	Element coupleInfo;

	@UiField
	DivElement passwordDiv;

	@UiField
	Label lblTryingLogin;

	@UiField
	Button btnDownloadApp;

	private boolean tryLoginOnSave;

	private static UserFormWidgetUiBinder uiBinder = GWT.create(UserFormWidgetUiBinder.class);

	interface UserFormWidgetUiBinder extends UiBinder<Widget, UserFormWidget> {
	}

	public UserFormWidget() {
		this.presenter = new UserFormPresenter(this, eventbus, operationManager, actionController);
		this.gender = new ValueListBox<Gender>(new HasLabelRenderer<Gender>("-- No especificado --"));
		List<Gender> availableGenders = new ArrayList<>();
		availableGenders.add(null);
		availableGenders.addAll(Arrays.asList(Gender.values()));
		this.gender.setAcceptableValues(availableGenders);
		initWidget(uiBinder.createAndBindUi(this));
	}

	public UserFormWidget(boolean passwordChangeEnabled) {
		this();
		this.setPasswordChangeEnabled(passwordChangeEnabled);
	}

	@UiHandler("userEmail")
	void onUserEmailChanged(ChangeEvent evt) {
		this.presenter.onUserEmailChanged();
	}

	@UiHandler("userEmail")
	void onUserEmailKeyPressed(KeyPressEvent evt) {
		if (this.enterPressed(evt)) {
			this.presenter.onUserEmailChanged();
		}
	}

	@Override
	public void checkEmail() {
		this.presenter.onCheckEmail();
	}

	@Override
	public Info userEmailCheckInfo() {
		return this.userEmailCheckInfo;
	}

	@Override
	public Info passwordCheckInfo() {
		return this.passwordCheckInfo;
	}

	@Override
	public Info extraInfo() {
		return this.extraInfo;
	}

	@Override
	public HasValue<String> userEmail() {
		return HasValueWrapper.<String> from(userEmail, true);
	}

	@Override
	public HasValue<Gender> gender() {
		return HasValueWrapper.from(gender, true);
	}

	@Override
	public HasValue<String> nickName() {
		return HasValueWrapper.from(nickName, true);
	}

	@Override
	public HasValue<String> password() {
		return HasValueWrapper.from(password, true);
	}

	@UiHandler("password")
	void onPasswordChanged(ChangeEvent evt) {
		this.presenter.onPasswordChanged();
	}

	@UiHandler("password2")
	void onPassword2Changed(ChangeEvent evt) {
		this.presenter.onPassword2Changed();
	}

	@Override
	public HasValue<String> password2() {
		return HasValueWrapper.from(password2, true);
	}

	@Override
	public HasEnabled userEmailEnabled() {
		return HasEnabledWrapper.from(userEmail, this);
	}

	@Override
	public HasText caption() {
		return HasTextWrapper.from(caption);
	}

	@Override
	public HasText saveActionText() {
		return HasTextWrapper.from(btnSave, this);
	}

	@Override
	public HasEnabled saveEnabled() {
		return HasEnabledWrapper.from(btnSave, this);
	}

	@UiHandler("btnSave")
	void onSaveButtonClicked(ClickEvent evt) {
		this.presenter.onSave();
	}

	@Override
	public void editUser(User user) {
		this.presenter.onEditUser(user);
	}

	@Override
	public boolean isEnabled() {
		return this.enabled;
	}

	@Override
	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
		if (enabled) {
			fieldSet.removeAttribute("disabled");
		} else {
			fieldSet.setAttribute("disabled", "disabled");
		}

	}

	@Override
	public HasLoader gettingUserIndicator() {
		return HasLoaderWrapper.fromVisible(this.gettingLoader);
	}

	@Override
	public HasLoader savingIndicator() {
		return HasLoaderWrapper.fromVisible(this.savingLoader);
	}

	@Override
	public void editUser(String userId) {
		this.presenter.onEditUser(userId);
	}

	@Override
	public boolean checkFormValidity() {
		return form.checkValidity();
	}

	@UiHandler("btnBreakUp")
	void onBreakUpButtonClicked(ClickEvent evt) {
		this.presenter.onBreakUp();
	}

	@UiHandler("btnDropSingleMode")
	void onDropSingleModeButtonClicked(ClickEvent evt) {
		this.presenter.onDropSingleMode();
	}

	@UiHandler("btnDropTestMode")
	void onDropTestModeButtonClicked(ClickEvent evt) {
		this.presenter.onDropTestMode();
	}

	@Override
	public HasVisibility couplePanel() {
		return HasVisibilityWrapper.from(couplePanel, this);
	}

	@Override
	public HasText coupleName() {
		return HasTextWrapper.from(coupleInfo);
	}

	@Override
	public HasLoader breakingUpIndicator() {
		return HasLoaderWrapper.fromVisible(this.breakingUpLoader);
	}

	@Override
	public HasLoader droppingSingleModeIndicator() {
		return HasLoaderWrapper.fromVisible(this.dropSingleModeLoader);
	}

	@Override
	public HasLoader droppingTestModeIndicator() {
		return HasLoaderWrapper.fromVisible(this.dropTestModeLoader);
	}

	public void setPasswordChangeEnabled(boolean enabled) {
		setVisible(passwordDiv, enabled);
	}

	public boolean isPasswordChangeEnabled() {
		return isVisible(passwordDiv);
	}

	@Override
	public HasLoader tryingLoginIndicator() {
		return HasLoaderWrapper.fromVisible(lblTryingLogin, this);
	}

	@Override
	public void setTryLoginOnSave(boolean tryLoginOnSave) {
		this.tryLoginOnSave = tryLoginOnSave;
	}

	@Override
	public boolean isTryLoginOnSave() {
		return tryLoginOnSave;
	}

	@Override
	public void nickNameFocus() {
		this.nickName.setFocus(true);
	}

	@Override
	public HasVisibility downloadApp() {
		return HasVisibilityWrapper.from(btnDownloadApp, this);
	}

	@UiHandler("btnDownloadApp")
	void onDownloadAppButtonClicked(ClickEvent evt) {
		this.presenter.onDownloadApp();
	}

	@Override
	public HasVisibility singlePanel() {
		return HasVisibilityWrapper.from(singlePanel, this);
	}

	@Override
	public HasVisibility testPanel() {
		return HasVisibilityWrapper.from(testPanel, this);
	}
}
